package nickthissen.iracing.parsing;

import android.text.TextUtils;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import org.jsoup.select.Elements;

import java.util.ArrayList;

import nickthissen.iracing.common.ForumListManager;
import nickthissen.iracing.datamodels.*;
import nickthissen.iracing.datamodels.Thread;

/**
 * Created by Nick on 4-6-13.
 */
public class RecentPopularParser extends Parser
{
    @Override
    protected Result doParse(String source)
    {
        Result result = new Result();
        ArrayList<RecentThread> threads = new ArrayList<RecentThread>();

        log("Start jsoup parsing recent/popular thread list");
        log(source);
        Document doc = Jsoup.parse(source);
        log("Finished jsoup parsing recent/popular thread list.");

        Element tableNode = doc.getElementById("forum");
        if (tableNode == null)
            log("Tablenode was null.");
        else
            log("Tablenode:" + tableNode.html());

        // Loop through rows of table
        ArrayList<Element> rows = Parsing.selectChildren(tableNode.select("tbody").first(), "tr"); // tableNode.select("tr");
        for (int trIndex = 0; trIndex < rows.size(); trIndex++)
        {
            Element tr = rows.get(trIndex);
            boolean rowIsParsed = false;

            // The top row (column headers) is the only row with attributes - skip it
            if (tr.attributes().size() > 0) continue;

            log("Start parsing table row: " + tr.toString());

            // Loop through columns
            ArrayList<Element> columns = Parsing.selectChildren(tr, "td[class]");// tr.select("td[class]");
            for (int tdIndex = 0; tdIndex < columns.size(); tdIndex++)
            {
                Element td = columns.get(tdIndex);

                // If row already parsed, skip it
                if (rowIsParsed) continue;

                log("Start parsing thread.");
                RecentThread thread = parseThread(tr);
                if (thread != null)
                {
                    threads.add(thread);
                    log("Thread created.");
                }
                else
                {
                    log("Thread NOT created.");
                }
                rowIsParsed = true;
            }
        }

        result.Success = true;
        result.Object = threads;
        return result;
    }

    private RecentThread parseThread(Element node)
    {
        RecentThread thread = new RecentThread();

        Elements nodeElements = node.select("td[class]");
        Element[] nodes = nodeElements.toArray(new Element[nodeElements.size()]);
        if (nodes.length != 7)
        {
            log("Not 7 td nodes.");
            return null;
        }

        Element iconNode = nodes[0];
        log("Icon node: " + iconNode.html());
        parseIcon(thread, iconNode);

        Element forumNode = nodes[1];
        log("Forum node: " + forumNode.html());
        Element link = forumNode.child(0);
        thread.ForumName = link.text();
        thread.ForumUrl = link.attr("href");

        int id = ForumListManager.getInstance().getForumIdFromUrl(thread.ForumUrl);
        Forum forum = ForumListManager.getInstance().forums.get(id);
        thread.ForumId = id;
        thread.ForumAbbreviation = forum.AbbreviatedName;

        Element topicNode = nodes[2];
        log("Topic node: " + topicNode.html());

        ArrayList<Element> imgElements = Parsing.selectChildren(topicNode, "img");
        if (imgElements.size() > 0)
        {
            Element img = imgElements.get(0);
            String src = img.attr("src");
            if (!TextUtils.isEmpty(src))
            {
                if (src.endsWith("iconClip.png")) {
                    thread.HasAttachments = true;
                }
                if (src.endsWith("iconPoll.png")) {
                    thread.IsPoll = true;
                }
            }
        }

        ArrayList<Element> linkNodes = Parsing.selectChildren(topicNode, "a");
        if (linkNodes.size() > 0)
        {
            Element titleNode = linkNodes.get(0);

            log("Title node: " + titleNode.html());

            //TODO: De-entitize
            thread.Url = titleNode.attr("href");
            thread.Id = Integer.parseInt(Parsing.getFilenameWithoutExtension(thread.Url).trim());
            thread.Title = titleNode.text();

            // Get last page
            if (linkNodes.size() > 1)
            {
                Element lastPageNode = linkNodes.get(linkNodes.size()-1);
                thread.LastPageUrl = lastPageNode.attr("href");
                thread.PageCount = Integer.parseInt(lastPageNode.text().trim());
            }
            else
            {
                thread.LastPageUrl = "";
                thread.PageCount = 1;
            }
        }

        Element authorNode = nodes[3];
        log("Author node: " + authorNode.html());
        Node linkNode = findFirstLinkNode(authorNode);
        if (linkNode != null)
        {
            thread.AuthorUrl = linkNode.attr("href");
            thread.Author = ((Element)linkNode).text();
        }

        parseRepliesViews(thread, nodes);

        Element lastNode = nodes[6];
        log("Last node: " + lastNode.html());
        parseLastReply(thread, lastNode);

        return thread;
    }

    private Node findFirstLinkNode(Element node)
    {
        return findFirstLinkNode(node, 5);
    }

    private Node findFirstLinkNode(Element node, int limit)
    {
        Node child = node.child(0);
        if (child == null) return null;
        if (child.nodeName().equals("a")) return child;

        int count = 0;
        while (count <= limit && child != null)
        {
            child = child.nextSibling();
            if (child != null && child.nodeName().equals("a")) return child;
        }

        return null;
    }

    private void parseIcon(RecentThread thread, Element node)
    {
        Node imgNode = node.childNode(0);
        if (imgNode == null || !imgNode.nodeName().equals("img")) return;

        String path = imgNode.attr("src");
        String name = Parsing.getFilenameWithoutExtension(path);
        if (name != null) thread.IconName = name.toLowerCase().trim();
    }

    private void parseRepliesViews(RecentThread thread, Element[] nodes)
    {
        String repliesString = nodes[4].text();
        String viewsString = nodes[5].text();

        thread.Replies = 0;
        thread.Views = 0;
        if (TextUtils.isDigitsOnly(repliesString)) {
            thread.Replies = Integer.parseInt(repliesString.trim());
        }
        if (TextUtils.isDigitsOnly(viewsString)) {
            thread.Views = Integer.parseInt(viewsString.trim());
        }
    }

    private void parseLastReply(RecentThread thread, Element node)
    {
        Element[] children = node.children().toArray(new Element[0]);
        Element scriptNode = children[0];
        Element userLinkNode = children[2];
        Element linkNode = children[3];

        log("Scriptnode: " + scriptNode);
        log("UserLinkNode: " + userLinkNode);
        log("LinkNode: " + linkNode);

        String dateString = scriptNode.toString();
        long unixMs = this.parseDateTimeScript(dateString);

        thread.LastMessageTime = unixMs;
        thread.LastMessageUser = userLinkNode.text().trim();
        thread.LatestReplyUrl = linkNode.attr("href");
    }

    @Override
    protected String getLogName()
    {
        return "RecentPopularParser";
    }

    @Override
    protected Result createDefaultResultObject()
    {
        Result result = new Result();
        result.Object = new ArrayList<RecentThread>();
        result.Message = "Error parsing recent/popular threads page.";
        return result;
    }
}
